package com.ruoyi.product.service.impl;

import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.product.domain.Categorie;
import com.ruoyi.product.domain.Products;
import com.ruoyi.product.mapper.ProductsMapper;
import com.ruoyi.product.service.IProductsService;
import com.ruoyi.redis.RedisDistributedLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 商品Service业务层处理（带Redis缓存）
 */
@CacheConfig(cacheNames = "products")
@Service
public class ProductsServiceImpl implements IProductsService {
    private static final String PRODUCT_KEY_PREFIX = "product:";
    private static final String PRODUCT_LIST_KEY_PREFIX = "product:list:";
    private static final Integer CACHE_EXPIRE_TIME = 30; // 缓存过期时间30分钟

    @Autowired
    private ProductsMapper productsMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
    @Autowired
    private RedisDistributedLock redisLock;
    // 库存Key前缀
    private static final String STOCK_KEY_PREFIX = "stock:";
    // 库存锁Key前缀
    private static final String LOCK_KEY_PREFIX = "lock:stock:";

    /**
     * 查询商品（带缓存）
     */
    @Override
    @Cacheable(key = "'products'+ #productId", unless = "#result == null")
    public Products selectProductsByProductId(Long productId) {
        String key = PRODUCT_KEY_PREFIX + productId;
        // 先从缓存获取
        Products product = redisCache.getCacheObject(key);
        if (product != null) {
            return product;
        }
        return productsMapper.selectProductsByProductId(productId);

    }

    /**
     * 查询商品列表（带缓存）
     */
    @Override
    @Cacheable(key = "'products:list' +  #products.productId", unless = "#result == null")
    public List<Products> selectProductsList(Products products) {
        String key = PRODUCT_LIST_KEY_PREFIX +products.getUserName();

        // 先从缓存获取
        List<Products> cachedList = redisCache.getCacheList(key);
        if (cachedList != null && !cachedList.isEmpty()) {
            return cachedList;
        }

        // 缓存没有则查询数据库
        List<Products> productList = productsMapper.selectProductsList(products);

        if (productList != null && !productList.isEmpty()) {
            // 存入缓存
            redisCache.setCacheList(key, productList);
            redisCache.expire(key, CACHE_EXPIRE_TIME, TimeUnit.MINUTES);
        }

        return productList;
    }

    /**
     * 新增商品（同步缓存）
     */
    @Transactional
    @Override
    @Cacheable(key = "'products' + #products.productId", unless = "#result == 0")
    public int insertProducts(Products products) {
        int rows = productsMapper.insertProducts(products);
        insertCategorie(products);
        if (rows > 0) {
            // 清除相关的列表缓存
            clearListCache(products.getUserName());
            initStock(products.getProductId(), products.getStockQuantity());
            // 缓存新创建的商品
            String key = PRODUCT_KEY_PREFIX + products.getUserName();
            redisCache.setCacheObject(key, products, CACHE_EXPIRE_TIME, TimeUnit.MINUTES);
        }
        return rows;
    }

    /**
     * 修改商品（同步缓存）
     */
    @Transactional
    @Override
    @Cacheable(key = "'products' + #products.productId", unless = "#result == 0")
    public int updateProducts(Products products) {
        productsMapper.deleteCategorieByCategoryId(products.getProductId());
        insertCategorie(products);
        int result = productsMapper.updateProducts(products);
        if (result > 0) {
            // 更新单个商品缓存
            updateStock(products.getProductId(), products.getStockQuantity());
            String key = PRODUCT_KEY_PREFIX + products.getUserName();
            redisCache.setCacheObject(key, products, CACHE_EXPIRE_TIME, TimeUnit.MINUTES);
            // 清除相关的列表缓存
            clearListCache(products.getUserName());
        }
        return result;
    }

    /**
     * 批量删除商品（同步缓存）
     */
    @Transactional
    @Override
    @Cacheable(key = "'products:list'+ #productId",unless = "#result == 0")
    public int deleteProductsByProductIds(Long[] productIds) {
        productsMapper.deleteCategorieByCategoryIds(productIds);
        // 先获取所有要删除的购物车项的用户名
        Set<String> userNames = new HashSet<>();

        for (Long productId : productIds) {
            Products products = productsMapper.selectProductsByProductId(productId);
            if (products != null) {
                userNames.add(products.getUserName());
            }
        }
        int result = productsMapper.deleteProductsByProductIds(productIds);

        if (result > 0) {
            for (Long productId : productIds) {
                clearStock(productId);
                redisCache.deleteObject(PRODUCT_KEY_PREFIX + productId);
            }
            // 清除相关用户的列表缓存
            for (String userName : userNames) {
                clearListCache(userName);
            }
        }
        return result;
    }

    /**
     * 删除商品（同步缓存）
     */
    @Transactional
    @Override
    @Cacheable(key = "'products' + #productId")
    public int deleteProductsByProductId(Long productId) {
        productsMapper.deleteCategorieByCategoryId(productId);
        Products  products= productsMapper.selectProductsByProductId(productId);
        int result = productsMapper.deleteProductsByProductId(productId);
        if (result > 0) {
            clearStock(productId);
            // 清除相关的列表缓存
            clearListCache(products.getUserName());
        }
        return result;
    }

    /**
     * 新增分类信息
     */
    public void insertCategorie(Products products) {
        List<Categorie> categorieList = products.getCategorieList();
        Long productId = products.getProductId();
        if (StringUtils.isNotNull(categorieList)) {
            List<Categorie> list = new ArrayList<Categorie>();
            for (Categorie categorie : categorieList) {
                categorie.setCategoryId(productId);
                list.add(categorie);
            }
            if (list.size() > 0) {
                productsMapper.batchCategorie(list);
            }
        }
    }


    /**
     * 清除商品列表缓存
     */
    private void clearListCache(String userName) {
        // 清除普通列表缓存
        redisCache.deleteObject(PRODUCT_KEY_PREFIX + userName);
        // 清除带详情的列表缓存
        redisCache.deleteObject(PRODUCT_LIST_KEY_PREFIX + userName);
    }

    @Override
    public void initStock(Long productId, Long stockQuantity) {
        String stockKey = STOCK_KEY_PREFIX + productId;
        redisTemplate.opsForValue().set(stockKey, stockQuantity);
    }

    // 更新库存
    public void updateStock(Long productId, Long stockQuantity) {
        String stockKey = STOCK_KEY_PREFIX + productId;
        redisTemplate.opsForValue().set(stockKey, stockQuantity);
    }

    // 清除库存
    public void clearStock(Long productId) {
        String stockKey = STOCK_KEY_PREFIX + productId;
        redisTemplate.delete(stockKey);
    }

    /**
     * 获取商品库存
     */
    @Override
    public Long getStock(Long productId) {
        String stockKey = getStockKey(productId);
        Object value = redisTemplate.opsForValue().get(stockKey);
        return value == null ? 0L : (Long) value;
    }



    /**
     * 扣减库存（带分布式锁）
     * @return 扣减成功返回true，库存不足返回false
     */
    @Override
    public Boolean decreaseStock(Long productId, Long stockQuantity) {
        String stockKey = getStockKey(productId);
        String lockKey = getLockKey(productId);

        // 获取分布式锁
        String lockValue = redisLock.acquireLock(lockKey);
        if (lockValue == null) {
            return false;
        }

        try {
            // 检查库存
            Long stock = getStock(productId);
            if (stock < stockQuantity) {
                return false;
            }

            // 扣减库存（原子操作）
            redisTemplate.opsForValue().decrement(stockKey, stockQuantity);
            return true;

        } finally {
            // 释放锁
            redisLock.releaseLock(lockKey, lockValue);
        }
    }

    /**
     * 增加库存（带分布式锁）
     */
    @Override
    public Boolean increaseStock(Long productId, Long stockQuantity) {
        String stockKey = getStockKey(productId);
        String lockKey = getLockKey(productId);

        // 获取分布式锁
        String lockValue = redisLock.acquireLock(lockKey);
        if (lockValue == null) {
            return false;
        }

        try {
            // 增加库存（原子操作）
            redisTemplate.opsForValue().increment(stockKey, stockQuantity);
            return false;

        } finally {
            // 释放锁
            redisLock.releaseLock(lockKey, lockValue);
        }
    }

    private String getStockKey(Long productId) {
        return STOCK_KEY_PREFIX + productId;
    }

    private String getLockKey(Long productId) {
        return LOCK_KEY_PREFIX + productId;
    }
}